#!/usr/bin/env python

import socket
import datetime
import time
import sys
import struct

# set this varibale to false to disable debug feature
DBG = False

# packet size
SZ = 100

# packet header length, LINK + IP + UDP
HDR_LEN = 16 + 20 + 8

if len(sys.argv) != 3:
    print "Usage: %s <ip> <port>" % sys.argv[0]
    sys.exit(0)

if DBG:
    SERVER = ("127.0.0.1", 46420)
    #SERVER = ("149.171.37.201", 46420)
else:
    SERVER = (sys.argv[1], int(sys.argv[2]))

print "connect to ", SERVER

# structrue of nettime packet
# uint_32 timestamp_secs
# uint_32 timestamp_msecs
# uint_32 packet_sequence
# uint_8* padding

# create a UDP socket, and set 1s timeout
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(1)

# initialize state
seq = sseq = 0x5858
ts = 0.0
padding = ""

while True:
    # increse packet sequence
    sseq += 1

    # encode packet, network data are big-endian
    buf0 = struct.pack(">8sI%ds" % SZ, "tel4642", sseq, padding)
    sseq += 1
    buf1 = struct.pack(">8sI%ds" % SZ, "tel4642", sseq, padding)

    # network IO
    s.sendto(buf0, SERVER)
    s.sendto(buf1, SERVER)
    try:
        data0, addr =  s.recvfrom(1024)
        data1, addr =  s.recvfrom(1024)
    except socket.timeout:
        print "oh no"
        continue

    # decode packet
    values = struct.unpack(">III%ds" % (len(data0) - 12), data0)

    ts0 =  values[0] + (values[1] / 1000000.0)
    seq0 = values[2]

    values = struct.unpack(">III%ds" % (len(data1) - 12), data1)

    ts1 =  values[0] + (values[1] / 1000000.0)
    seq1 = values[2]

    # validate packet
    if (seq1 - seq0) != 1:
        print "packet lost"
        time.sleep(1)
        continue

    # update timestmap

    # calculate bandwidth in Mbps
    try:
        bw = (HDR_LEN + len(data0)) / (ts1 - ts0) / 1000000.0
    except ZeroDivisionError:
        # this should be wrong
        bw = sys.maxint

    print "speed %fMbps" % bw

    # sleep 1s
    time.sleep(1)
